package net.sf.nlp.ltag.parser.dot;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import net.sf.nlp.ltag.data.LTAGNode;
import net.sf.nlp.ltag.data.LTAGTree;
import net.sf.nlp.ltag.parser.LTAGState;
import net.sf.nlp.ltag.parser.LeafNode;
import net.sf.nlp.ltag.parser.ParserAlgAbstract;

public abstract class DotAlgAbstract extends ParserAlgAbstract
{
	protected static Logger logger =  Logger.getLogger(DotAlgAbstract.class);
	
	protected List<LTAGState> matchedStates = Collections.synchronizedList(new ArrayList<LTAGState>());
	
	public DotAlgAbstract(Map<String, List<LTAGTree>> ltagMap)
	{
		super(ltagMap);
	}

	@Override
	public LTAGState generateLTAGState(LTAGTree tree, LTAGState state, int step) 
	{
		DotState newState = new DotState(tree);
		
		if (state != null)
		{
			newState.setScanedNodes(((DotState)state).cloneScanedNodes());
			newState.setFreq(state.getFreq());
		}
		
		return newState;
	}
	
	protected void calculateTask(List<LTAGState> stateSet)
	{
		for (int i = 0; i < stateSet.size(); i++)
		{
			int size = stateSet.size();
			LTAGState state = stateSet.get(i);
			
			if (state.isMatched(words))
				matchedStates.add(state);
			else
				calculateTask(stateSet, state);
			
			System.out.println("i=" + i + ";stateSet.size()=" + stateSet.size() + "; add=" + (stateSet.size()-size));
		}
		
		for (int i = 0; i < matchedStates.size(); i++)
		{
			if (logger.isInfoEnabled())
				logger.info(matchedStates.get(i).toString());
		}
	}
	
	protected void calculateTask(List<LTAGState> stateSet, LTAGState state)
	{
		predictor(stateSet, state);
	}
	
	private void predictor(List<LTAGState> stateSet, LTAGState state)
	{
		LTAGNode node = state.getNode();
		LTAGTree tree = state.getTree();
		int step = state.getStep();
		
		if ("$".equals(node.getType()))
		{
			List<LTAGState> substitutionStates = getSubstitutionState(state, step);
			
			for (LTAGState substitutionState : substitutionStates)
			{
				((DotState)substitutionState).getScanedNodes().add(new LeafNode(tree, node));
				
				stateSet.add(substitutionState);
			}
			
			return;
		}
		else if ("*".equals(node.getType()) && node.getLeafIndex() == 0)
		{
			LeafNode nextTreeNode = ((DotState)state).getAndRemoveLastScanedNodes();
			
			LTAGState clonedState = state.clone();
			
			((DotState)clonedState).getScanedNodes().add(new LeafNode(tree, node));
			
			clonedState.setId(stateCount.getAndIncrement());
			clonedState.setPreviousState(state);
			clonedState.setTree(nextTreeNode.getTree());
			clonedState.setNode(nextTreeNode.getTree().getNodeByLocation(nextTreeNode.getLeafNode().getLocation() + 1));
			
			stateSet.add(clonedState);
			return;
		}
		else if (node.getChildren() != null && node.getChildren().size() > 0)
		{
			if (!"*".equals(node.getType()) && !"#".equals(node.getType()))
			{
				List<LTAGState> adjunctStates = getAdjunctState(state, step);
				
				for (LTAGState adjunctState : adjunctStates)
				{
					((DotState)adjunctState).getScanedNodes().add(new LeafNode(tree, node));
					
					stateSet.add(adjunctState);
				}
			}
		}
		
		LeafNode nextTreeNode = ((DotState)state).getNextTreeNode();
		if (nextTreeNode == null)
			return;
		
		if (node.getLeafIndex() == tree.getLeafNodeCount() - 1 && !validateStatistic(state, bestResutCount))
			return;
		
		
		LTAGState clonedState = state.clone();
			
		clonedState.setId(stateCount.getAndIncrement());
		clonedState.setPreviousState(state);
		clonedState.setTree(nextTreeNode.getTree());
		clonedState.setNode(nextTreeNode.getLeafNode());
		
		clonedState.addNoAdjunctionFreq();
		
		stateSet.add(clonedState);
		
	}
}
